python实现维吉尼亚加密解密以及利用拟重合指数法爆破

# -*- coding: utf-8 -*-
"""
"""


# !/usr/bin/env python


import string
import pprint


a_z = string.ascii_lowercase
A_Z = string.ascii_uppercase


# 生成维吉尼亚表
def produce(location):
s = ""
s += A_Z[location:] + A_Z[0:location]
return s

def produce_table():
dic = {}
for i in range(0, 26):
dic[a_z[i]] = produce(i)
return dic


# 生成表
table = produce_table()
#pprint.pprint(table)


def filter_claer(clear):
result = ""
clear = clear.lower()
for i in clear:
if 97 <= ord(i) <= 122:
result += i
return result


# 加密
def encrypt(clear_content, key):
clear_content = get_trim_text(clear_content)
result = ""
length = len(key)
loca = 0
for i in clear_content:
result += table[i][a_z.index(key[loca])]  # table[i]代表明文字符所在列,a_z[index](key[loca])表示秘钥字符
loca += 1
loca = loca % length
return result.lower()

#解密
def decrypt(cipher, key):
result = ""
length = len(key)
loca = 0
for i in cipher.upper():
result += a_z[table[key[loca]].index(i)]
# table[key[loca]]表示秘钥字符串所在行,index(i)表示明文字符的索引,查找a_z
loca += 1
loca = loca % length
return result


def get_trim_text(text):
result = ""
clear = text.lower()
for i in clear:
if 97 <= ord(i) <= 122:
result += i
return result




# 求秘钥长度
def get_key_length(text):
length = len(text)
List_word_chance = {}
for m in range(1, 18):
List_avgCipher = []
for time in range(0, m):
temp = text[time::m]
List_avgCipher.append(temp)
# print(List_avgCipher)
lis = []
for i in List_avgCipher:
all_word = set(i)
chance = 0
for j in all_word:
chance += i.count(j) * (i.count(j) - 1)
lis.append(chance / ((len(i) * len(i) - 1)))
List_word_chance[m] = sum(lis) / m
result = []
for i, v in List_word_chance.items():
result.append([i, v, abs(v - 0.065)])
result = sorted(result, key=lambda s: s[2])
return result



# 获取密钥长度
def getKeyLen(cipherText):  
keylength = 1
maxCount = 0
for step in range(3, 18):  # 循环密钥长度
count = 0
for i in range(step, len(cipherText) - step):
if cipherText[i] == cipherText[i + step]:
count += 1
if count > maxCount:
maxCount = count
keylength = step
return keylength




# 统计字母频度
def countList(lis):
li = []
alphabet = [chr(i) for i in range(97, 123)]
for c in alphabet:
count = 0
for ch in lis:
if ch == c:
count += 1
li.append(float(count) / len(lis))
return li




# 根据密钥长度将密文分组
def textToList(text, length):
text = get_trim_text(text)
textMatrix = []
row = []
index = 0
for ch in text:
row.append(ch)
index += 1
if index % length == 0:
textMatrix.append(row)
row = []
textMatrix.append(row)
return textMatrix




# 获取密钥
def getKey(text, length):
text = get_trim_text(text)
key = []  # 定义空白列表用来存密钥
alphaRate = [0.08167, 0.01492, 0.02782, 0.04253, 0.12705, 0.02228, 0.02015, 0.06094, \
            0.06996, 0.00153, 0.00772, 0.04025, 0.02406, 0.06749, 0.07507, 0.01929, \
            0.0009, 0.05987, 0.06327, 0.09056, 0.02758, 0.00978, 0.02360, 0.0015, 0.01974, 0.00074]
matrix = textToList(text, length)
for i in range(length):
w = [row[i] for row in matrix if len(row) > i]  # 获取每组密文
if length == 6 and i == 0:
print('**********************************')
print(w)
li = countList(w)
powLi = []  # 算乘积
for j in range(26):
Sum = 0.0
for k in range(26):
Sum += alphaRate[k] * li[k]
powLi.append(Sum)
li = li[1:] + li[:1]  # 循环移位
if length == 6 and i == 0:
print('**********************************')
print(powLi)
Abs = 100
ch = ''
for j in range(len(powLi)):
if abs(powLi[j] - 0.065546) < Abs:  # 找出最接近英文字母重合指数的项
Abs = abs(powLi[j] - 0.065546)  # 保存最接近的距离,作为下次比较的基准
ch = chr(j + 97)
key.append(ch)
return key

if __name__ == '__main__':
prompt = """选择
(e)加密
(d)解密
(c)爆破
(q)退出
请输入你的选择: 
"""
while (True):
choice = input(prompt)
if choice == 'e':
p = input("请输入明文 ")
k = input("输入加密秘钥 ")
print("密文为: %s" % (encrypt(p, k)))
elif choice == 'd':
c = input("请输入密文: ")
k = input("请输入解密秘钥: ")
print("明文为: %s" % (decrypt(c, k)))
elif choice == 'q':
break
elif choice == 'c':
key_lengths = []
c = input("please enter ciphertext: ")
key_lengths = getKeyLen(c)
print("使用Kasiski得到的秘钥长度为:" + str(key_lengths))
print("使用重合指数得到的分组概率从大到小为\n"
     "[分组数,平均重合指数,绝对值(平均-0.065]\n")
key_lengths_chonghe = get_key_length(c)
for i in key_lengths_chonghe:
print(i)
if key_lengths_chonghe[0][0]==key_lengths:
print("秘钥长度为%d"%key_lengths)
key = ""
for i in getKey(c, key_lengths_chonghe[0][0]):
key += i
print("明文是 %s,\n 密钥是 %s\n" \
     % (decrypt(c, key), key))
else:
print("尝试前面3组秘钥长度:")
for j in range(0,3):
key = ""
for i in getKey(c, key_lengths_chonghe[j][0]):
key += i
print("明文是 %s,\n 密钥是 %s\n" \
     % (decrypt(c, key), key))
else:
print("不合理的输入,请重新输入")
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值